package cn.edu.zut.soft.graduate.gradesCenter.bo.Impl;

import cn.edu.zut.soft.basic.core.model.bo.CommonResult;
import cn.edu.zut.soft.basic.core.model.dao.Criteria;
import cn.edu.zut.soft.basic.core.model.dao.Example;
import cn.edu.zut.soft.graduate.base.bo.BasicBOImpl;
import cn.edu.zut.soft.graduate.base.dao.BasicDAO;
import cn.edu.zut.soft.graduate.base.predicate.InfoKeyPredicate;
import cn.edu.zut.soft.graduate.core.constant.GradeTimeType;
import cn.edu.zut.soft.graduate.core.constant.GradeType;
import cn.edu.zut.soft.graduate.core.constant.InfoType;
import cn.edu.zut.soft.graduate.core.constant.config.IKEY;
import cn.edu.zut.soft.graduate.core.constant.config.TopicPhase;
import cn.edu.zut.soft.graduate.core.constant.config.TopicPhaseAble;
import cn.edu.zut.soft.graduate.core.design.BasicGradeStrategy;
import cn.edu.zut.soft.graduate.core.design.BasicInfoStrategy;
import cn.edu.zut.soft.graduate.core.design.GradeStrategy;
import cn.edu.zut.soft.graduate.core.design.InfoStrategy;
import cn.edu.zut.soft.graduate.core.model.Impl.Grade;
import cn.edu.zut.soft.graduate.core.model.Impl.Identity;
import cn.edu.zut.soft.graduate.core.model.Impl.Info;
import cn.edu.zut.soft.graduate.core.model.view.TeacherGroupVO;
import cn.edu.zut.soft.graduate.core.query.GradeQuery;
import cn.edu.zut.soft.graduate.core.vo.LoginVO;
import cn.edu.zut.soft.graduate.core.vo.UserDescVO;
import cn.edu.zut.soft.graduate.gradesCenter.bo.GradeBO;
import cn.edu.zut.soft.graduate.gradesCenter.dao.GradesDAO;
import cn.edu.zut.soft.graduate.groupCenter.bo.TeacherGroupBO;
import cn.edu.zut.soft.graduate.userCenter.bo.IdentityBO;
import cn.edu.zut.soft.graduate.userCenter.bo.InfoBO;
import cn.edu.zut.soft.graduate.userCenter.dao.InfoDAO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * <p>文件名称：GradeBOImpl.java</p>
 * <p>文件描述：</p>
 * <p>版权所有： 版权所有(C)2011-2099</p>
 * <p>公   司： 口袋购物 </p>
 * <p>内容摘要： </p>
 * <p>其他说明： </p>
 * <p>完成日期：17/1/3 下午1:57</p>
 *
 * @author yangxiaotian@weidian.com
 * @version 1.0
 */
@Service
public class GradeBOImpl extends BasicBOImpl<Grade, GradeQuery> implements GradeBO {

    @Resource
    private GradesDAO<Grade> gradesDAO;

    @Resource
    private InfoDAO<Info> infoDAO;

    @Resource
    private IdentityBO identityBO;

    @Resource
    private InfoBO infoBO;

    @Resource
    private TeacherGroupBO teacherGroupBO;

    @Override
    protected BasicDAO<Integer, Grade> getDAO() {
        return gradesDAO;
    }

    @Override
    protected List<Criteria> Query(GradeQuery gradeQuery) {
        Criteria criteria = new Criteria();
        if (gradeQuery.getGradeType() != null) {
            criteria.andEqualTo("`type`", gradeQuery.getGradeType());
        }
        if (gradeQuery.getKey() != null) {
            criteria.andEqualTo("`key`", gradeQuery.getKey());
        }
        if (gradeQuery.getValue() != null) {
            criteria.andEqualTo("`value`", gradeQuery.getValue());
        }
        if (CollectionUtils.isNotEmpty(gradeQuery.getValueList())) {
            criteria.andIn("`value`", gradeQuery.getValueList());
        }
        if (gradeQuery.getRole() != null) {
            criteria.andEqualTo("`identity_role`", gradeQuery.getRole());
        }
        if (gradeQuery.getIdentityId() != null) {
            criteria.andEqualTo("identity_id", gradeQuery.getIdentityId());
        }
        if (gradeQuery.getDel() != null) {
            criteria.andEqualTo("del", gradeQuery.getDel());
        } else {
            criteria.andEqualTo("del", IKEY.ZERO);
        }
        return Collections.singletonList(criteria);
    }

    /**
     * <p>功能描述：保存开题成绩</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-02-20 00:09:10</p>
     * <p>其他:改造适应一次开题成绩/二次开题成绩
     * 流程:判断成绩表是否存在成绩 若存在不执行,只执行未存在成绩表成绩的学生
     * 保存一辩成绩/二辩成绩
     * 现有2种情况;
     * 1、未参加1辩开题 直接进入二辩 info表中没有openGrade_One
     * 2、进入一辩开题 未通过进入二辩 info表中存在openGrade_One 存在openGrade_Two
     * </p>
     *
     * @param gradeStrategy 成绩
     * @param id            学生ID
     * @param operator      操作者
     * @param time          第几次答辩  1/2
     * @return
     */
    @Override
    @Transactional
    public Grade save(GradeStrategy gradeStrategy, Integer id, String operator, Integer time) {
        //校验身份
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号错误,请重新输入");
        // 查询成绩表中是否存在成绩
        List<Grade> resultList = getGrade(gradeStrategy.getKey(), id);
        CommonResult<Grade> result = null;
        Boolean stopGrade = checkingStopById(id);
        if (resultList.isEmpty() && !stopGrade) { //若存在成绩则该走重置服务
            Boolean saveGrade = saveGrade(gradeStrategy, identity, operator);
            if (saveGrade) {
                Info info = infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), id, operator);
                if (info != null) {
                    if (time == IKEY.ONE) {
                        Info openOne = infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.ONE_REPLY), null), id, operator);
                    } else if (time == IKEY.TWO) {
                        Info openTwo = infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.TWO_REPLY), null), id, operator);
                    } else if (time == IKEY.END) {
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.GRADE_STOP_KEY, IKEY.OPEN_GRADE), id, operator);
                    }
                }
            }
        } else {
            result = CommonResult.errorReturn("该成绩学生已存在!");
        }
        return result != null ? result.getData() : null;
    }


    /**
     * <p>功能描述：重置开题成绩</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-02-20 00:00:33</p>
     *
     * @param gradeStrategy
     * @param id
     * @param operator
     * @return
     */

    @Override
    @Transactional
    public Grade restGradeRecorde(InfoStrategy gradeStrategy, Integer id, String operator) {
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号错误,请重新输入");
        //获取grade表中成绩数据
        List<Grade> resultList = getGrade(gradeStrategy.getKey(), id);
        CommonResult<Grade> saveResult = null;
        Boolean stopGrade = checkingStopById(id);
        if (!resultList.isEmpty() && !stopGrade) { // 若成绩表不存在该成绩。直接跳出
            //把编辑记录变为历史记录
            Grade historyGrade = resultList.get(0);
            historyGrade.setDel(-1);
            CommonResult<Grade> updateResult = update(historyGrade, operator);
            //新成绩纪录
            Grade newRecorde = new Grade();
            newRecorde.setType(gradeStrategy.getType().name());
            newRecorde.setKey(gradeStrategy.getKey());
            newRecorde.setValue(gradeStrategy.getValue());
            newRecorde.setIdentityId(identity.getId());
            newRecorde.setIdentityName(identity.getName());
            newRecorde.setIdentityRole(identity.getRole());
            saveResult = this.save(newRecorde, operator);
            if (saveResult.isSuccess()) {// 插入新记录成功
                //根据key查询出所有该key记录
                List<Info> infoList = infoBO.getInfo(gradeStrategy.getKey(), id);
                if (!infoList.isEmpty()) {
                    if (infoList.size() > 1) {
                        //若有多条数据时,全部逻辑删除
                        for (Info info : infoList) {
                            info.setDel(-1);
                            infoBO.update(info, operator);
                        }
                        //插入一条最新新纪录
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), id, operator);
                    } else {
                        //当数据为1条时,直接进行编辑
                        Info info = infoList.get(0);
                        info.setValue(gradeStrategy.getValue());
                        infoBO.update(info, operator);
                    }
                }
            }
        }
        return saveResult != null ? saveResult.getData() : null;
    }


    /**
     * 二次成绩
     * 查询是否有成绩
     * 有成绩的话先逻辑删除 新增二次成绩
     * info 表中新增openGrade_Two成绩
     * 方法有些多余需要重构  @TODO 重构
     *
     * @param infoStrategy
     * @param id
     * @param operator
     * @return
     */
    @Override
    @Transactional
    public Grade restGradeRecorde(InfoStrategy infoStrategy, Integer id, String operator, Integer times) {
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号参数错误,请重新输入");
        // 查询成绩表中是否存在成绩
        List<Grade> resultList = getGrade(infoStrategy.getKey(), id);
        CommonResult<Grade> saveResult = null;
        if (!resultList.isEmpty()) {
            //把编辑记录变为历史记录
            Grade historyGrade = resultList.get(0);
            historyGrade.setDel(-1);
            update(historyGrade, operator);
            //新成绩纪录
            Grade newRecorde = new Grade();
            newRecorde.setType(infoStrategy.getType().name());
            newRecorde.setKey(infoStrategy.getKey());
            newRecorde.setValue(infoStrategy.getValue());
            newRecorde.setIdentityId(identity.getId());
            newRecorde.setIdentityName(identity.getName());
            newRecorde.setIdentityRole(identity.getRole());
            saveResult = this.save(newRecorde, operator);
            if (saveResult.isSuccess()) {
                //若是被终止答辩
                Boolean stopGrade = checkingStopById(id);
                if (stopGrade) { // 已经被终止答辩 重置为正常
                    if (times != -1) {
                        List<Info> stopInfo = infoBO.getInfo(IKEY.GRADE_STOP_KEY, id);
                        if (CollectionUtils.isEmpty(stopInfo) || stopInfo.size() > 1) {
                            logger.error("rest open grade failed , stopInfo : " + JSONObject.toJSONString(stopInfo));
                        } else {
                            Info stInfo = stopInfo.get(0);
                            stInfo.setDel(-1);
                            infoBO.update(stInfo, operator);
                            Info info = infoBO.save(new BasicInfoStrategy(InfoType.GRADE, infoStrategy.getKey(), infoStrategy.getValue()), id, operator);
                            if (info != null) {
                                if (times == IKEY.ONE) {
                                    infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.ONE_REPLY), null), id, operator);
                                } else if (times == IKEY.TWO) {
                                    infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.TWO_REPLY), null), id, operator);
                                }
                            } else {
                                logger.error(" save Info message on rest open grade");
                            }
                        }
                    }
                } else { //正常 现在可以重置为 一遍、二辩、终止
                    List<Info> openGradeInfo = infoBO.getInfo(IKEY.OPEN_GRADE, id);
                    List<Info> oneOpenMark = infoBO.getInfo(IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.ONE_REPLY), id);
                    List<Info> twoOpenMark = infoBO.getInfo(IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.TWO_REPLY), id);
                    //清除开题成绩
                    if (CollectionUtils.isNotEmpty(openGradeInfo)) {
                        Info openInfo = openGradeInfo.get(0);
                        openInfo.setDel(-1);
                        infoBO.update(openInfo, operator);
                    }
                    //清除一辩标志
                    if (CollectionUtils.isNotEmpty(oneOpenMark)) {
                        Info oneInfo = oneOpenMark.get(0);
                        oneInfo.setDel(-1);
                        infoBO.update(oneInfo, operator);
                    }
                    //清除二辩标志
                    if (CollectionUtils.isNotEmpty(twoOpenMark)) {
                        Info twoOpen = twoOpenMark.get(0);
                        twoOpen.setDel(-1);
                        infoBO.update(twoOpen, operator);
                    }
                    if (times == IKEY.ONE) {
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, infoStrategy.getKey(), infoStrategy.getValue()), id, operator);
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.ONE_REPLY), null), id, operator);
                    } else if (times == IKEY.TWO) {
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, infoStrategy.getKey(), infoStrategy.getValue()), id, operator);
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.getReplyTimeKey(IKEY.OPEN_GRADE, IKEY.TWO_REPLY), null), id, operator);
                    } else if (times == IKEY.END) {
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.GRADE_STOP_KEY, IKEY.GRADE_STOP_KEY), id, operator);
                    }
                }

            }

        }
        return saveResult != null ? saveResult.getData() : null;
    }


    @Override
    public List<Info> findAllGrade(LoginVO loginVO) {
        UserDescVO userDescVO = identityBO.userPersonal(loginVO.getId());
        List<Info> gradeList = new ArrayList<>();
        //清理出答辩成绩
        CollectionUtils.select(userDescVO.getInfoList(), InfoKeyPredicate.create(InfoType.GRADE, Arrays.<TopicPhaseAble>asList(TopicPhase.Value.values())));
        return gradeList;
    }

    @Override
    public CommonResult<Grade> saveInterimGrade(GradeStrategy gradeStrategy, Integer id, String operator) {
        if (gradeStrategy == null || id == null || StringUtils.isEmpty(operator)) {
            return null;
        }
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号错误,请重新输入");
        //校验开题成绩是否通过
        boolean openGrade = checkOpenGrade(identity.getId());
        //校验是否终止答辩
        boolean stopGrade = checkingStopById(identity.getId());
        //查询中期成绩是否存在
        List<Grade> gradeResult = getGrade(gradeStrategy.getKey(), id);
        CommonResult<Grade> result = null;
        if (openGrade && CollectionUtils.isEmpty(gradeResult) && !stopGrade) {
            Boolean saveGrade = saveGrade(gradeStrategy, identity, operator);
            if (saveGrade) {
                //终止答辩
                if (gradeStrategy.getKey().equals(IKEY.GRADE_STOP_KEY)) {
                    infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.GRADE_STOP_KEY, IKEY.INTERIM_GRADE), id, operator);
                } else {
                    infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), id, operator);
                }
            } else {
                logger.error("save IntrimGrade failed, grade : " + JSON.toJSONString(gradeStrategy));
                return CommonResult.errorReturn("保存开题成绩失败!");
            }
        } else {
            logger.info("student save interim grade failed, student:" + JSON.toJSONString(identity) + "operator:" + operator + " , grade:" + gradeStrategy.getValue());
            return CommonResult.errorReturn("学生:" + identity.getName() + "该学生开题成绩未通过或已终止答辩!");
        }
        return CommonResult.successReturn(result.getData());
    }

    @Override
    public CommonResult<Grade> restInterimGrade(GradeStrategy gradeStrategy, Integer id, String operator) {
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号参数错误,请重新输入");
        // 查询成绩表中是否存在成绩
        List<Grade> resultList = getGrade(gradeStrategy.getKey(), id);
        CommonResult<Grade> saveResult = null;
        if (!resultList.isEmpty()) {
            Grade historyGrade = resultList.get(0);
            historyGrade.setDel(-1);
            update(historyGrade, operator);
            //新成绩纪录
            Boolean saveGrade = saveGrade(gradeStrategy, identity, operator);
            if (saveGrade) {
                //校验是否终止答辩
                boolean checkStopGrade = checkingStopById(id);
                if (checkStopGrade) {
                    List<Info> infoList = infoBO.getInfo(IKEY.GRADE_STOP_KEY, id);
                    Info info = infoList.get(0);
                    //校验是否是 因中期导致的终止答辩
                    if (info.getValue().equals(IKEY.INTERIM_GRADE)) {
                        info.setDel(-1);
                        infoBO.update(info, operator);
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), id, operator);
                    }
                } else {
                    //判断重置结果是否是 终止答辩
                    List<Info> interimGradeInfoList = Lists.newArrayList();
                    if (gradeStrategy.getKey().equals(IKEY.GRADE_STOP_KEY)) {
                        interimGradeInfoList = infoBO.getInfo(IKEY.INTERIM_GRADE, identity.getId());
                    } else {
                        interimGradeInfoList = infoBO.getInfo(gradeStrategy.getKey(), identity.getId());
                    }
                    if (CollectionUtils.isNotEmpty(interimGradeInfoList)) {
                        Info info = interimGradeInfoList.get(0);
                        info.setDel(-1);
                        infoBO.update(info, operator);
                        if (gradeStrategy.getKey().equals(IKEY.GRADE_STOP_KEY)) {
                            infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.GRADE_STOP_KEY, IKEY.INTERIM_GRADE), id, operator);
                        } else {
                            infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), id, operator);
                        }
                    } else {
                        logger.error("get interimGradeInfoList is null");
                        return CommonResult.errorReturn("System error get InterimGrade is null !");
                    }
                }
            } else {
                logger.info("student update interim grade failed, student:" + JSON.toJSONString(identity) + "operator:" + operator + " , grade:" + gradeStrategy.getValue());
                return CommonResult.errorReturn("重置中期成绩失败!");
            }
        } else {
            logger.error("grade is null , gradeStrategy:" + JSON.toJSONString(gradeStrategy) + " userId : " + id + ", operator:" + operator);
            return CommonResult.errorReturn("System error Interim Grade is null !");
        }
        return CommonResult.successReturn(saveResult.getData());
    }

    @Override
    public CommonResult<Boolean> saveSystemGrade(GradeStrategy gradeStrategy, Integer id, GradeTimeType times, String operator) {
        if (gradeStrategy == null || id == null || times == null) {
            return CommonResult.errorReturn(" System param error !");
        }
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号参数错误,请重新输入");
        Boolean checkInterimGrade = checkInterimGrade(id);
        Boolean checkStopRole = checkingStopById(id);
        CommonResult<Boolean> result = new CommonResult<Boolean>(true, "");
        if (checkInterimGrade && !checkStopRole) {
            List<Grade> systemGrade = getGrade(gradeStrategy.getKey(), identity.getId());
            if (CollectionUtils.isEmpty(systemGrade)) {
                Boolean saveResult = saveGrade(gradeStrategy, identity, operator);
                if (saveResult) {
                    saveInfoByTimes(gradeStrategy, times, id, operator);
                    result.setData(true);
                    result.setSuccess(true);
                    result.setErrorMsg("添加成功系统验收成绩成功!");
                } else {
                    logger.error(" sace grade failed , gradeStrategy : " + JSON.toJSONString(gradeStrategy));
                }
            } else {
                logger.error("System garde is not null,  studentId :" + id);
            }
        } else {
            result.setData(false);
            result.setSuccess(false);
            result.setErrorMsg("学生姓名: " + identity.getName() + " , 该学生中期成绩未操作或已终止答辩!");
        }
        return result;
    }

    @Override
    public CommonResult<Boolean> restSystemGrade(GradeStrategy gradeStrategy, Integer id, GradeTimeType times, String operator) {
        if (gradeStrategy == null || id == null || times == null) {
            return CommonResult.errorReturn(" System param error !");
        }
        Identity identity = identityBO.get(id);
        Assert.notNull(identity, "编号参数错误,请重新输入");
        CommonResult<Boolean> result = new CommonResult<Boolean>(true, "");
        List<Grade> systemGrade = getGrade(gradeStrategy.getKey(), identity.getId());
        if (CollectionUtils.isNotEmpty(systemGrade)) {
            //将原数据删除
            Grade syetemGradeOnce = systemGrade.get(0);
            syetemGradeOnce.setDel(-1);
            this.update(syetemGradeOnce, operator);
            //重新插入数据
            Boolean saveResult = saveGrade(gradeStrategy, identity, operator);
            if (saveResult) {
                Info historySystemGradeInfo = null;
                List<Info> infoList = infoBO.getInfo(IKEY.GRADE_STOP_KEY, identity.getId());
                if (CollectionUtils.isEmpty(infoList)) {
                    //若不是终止答辩
                    Example infoSystemExample = new Example();
                    infoSystemExample.createCriteria().andLike("`key`", IKEY.SYSTEM_GRADE + "%")
                            .andEqualTo("identity_id", id)
                            .andEqualTo("del", 0);
                    List<Info> systemGradeResult = infoDAO.selectByExample(infoSystemExample);
                    Example infoReplyExample = new Example();
                    infoReplyExample.createCriteria().andLike("`key`", IKEY.REPLY_GRADE + "%")
                            .andEqualTo("`value`", IKEY.SYSTEM_GRADE)
                            .andEqualTo("identity_id", id)
                            .andEqualTo("del", 0);
                    List<Info> replayGradeResult = infoDAO.selectByExample(infoReplyExample);
                    replayGradeResult.addAll(systemGradeResult);
                    for (Info info : replayGradeResult) {
                        info.setDel(-1);
                        infoBO.update(info, operator);
                    }
                } else {
                    historySystemGradeInfo = infoList.get(0);
                    historySystemGradeInfo.setDel(-1);
                    infoBO.update(historySystemGradeInfo, operator);
                }
                saveInfoByTimes(gradeStrategy, times, id, operator);
                result.setSuccess(true);
                result.setData(true);
                result.setErrorMsg("重置系统验收成绩成功!");
            } else {
                //成绩插入失败
                logger.error(" rest grade failed , gradeStrategy : " + JSON.toJSONString(gradeStrategy));
                result.setSuccess(false);
                result.setData(false);
                result.setErrorMsg("重置系统验收成绩-插入成绩失败, id:" + id);
            }
        } else {
            //重置---没有成绩
            logger.error("System garde is not null,  studentId :" + id);
            result.setSuccess(false);
            result.setData(false);
            result.setErrorMsg("重置成绩-系统验收成绩为null! , id:" + id);
        }
        return result;
    }

    @Override
    public CommonResult<Boolean> saveReplyGrade(GradeStrategy gradeStrategy, Integer id, String operator) {
        if (gradeStrategy == null || id == null) {
            return CommonResult.errorReturn("System param error! ");
        }
        Identity identity = identityBO.get(id);
        if (identity == null) {
            return CommonResult.errorReturn("该学生不存在!");
        }
        CommonResult<Boolean> result = new CommonResult<Boolean>(false, "");
        Boolean checkStop = checkingStopById(identity.getId());
        Boolean checkSystem = checkSystemGrade(identity.getId());
        if (!checkStop && checkSystem) {
            List<Grade> relpyGrade = getGrade(gradeStrategy.getKey(), identity.getId());
            //该种成绩类型已经存在
            if (CollectionUtils.isEmpty(relpyGrade)) {
                Boolean saveGrade = saveGrade(gradeStrategy, identity, operator);
                //保存成绩成功
                if (saveGrade) {
                    Info saveInfo = infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), identity.getId(), operator);
                    if (saveInfo != null) {
                        result.setSuccess(true);
                    } else {
                        logger.error("save info failed , gradeStrategy :" + JSONObject.toJSONString(gradeStrategy));
                    }
                } else {
                    logger.error("save grade failed , gradeStrategy :" + JSONObject.toJSONString(gradeStrategy));
                }
            } else {
                result.setErrorMsg("该学生已经存在该种成绩,请执行重置成绩操作!");
            }
        } else {
            result.setErrorMsg("该学生系统验收成绩未给予或已终止答辩!");
        }
        return result;
    }

    @Override
    public CommonResult<Boolean> restReplyGrade(GradeStrategy gradeStrategy, Integer id, String operator) {
        if (gradeStrategy == null || id == null) {
            return CommonResult.errorReturn("System param error !");
        }
        CommonResult<Boolean> result = new CommonResult<Boolean>(false, "");
        Identity identity = identityBO.get(id);
        if (identity == null) {
            return CommonResult.errorReturn("该学生存在!");
        }
        List<Grade> gradeList = getGrade(gradeStrategy.getKey(), identity.getId());
        if (!CollectionUtils.isEmpty(gradeList)) {
            Grade history = gradeList.get(0);
            history.setDel(-1);
            update(history, operator);
            //保存一条新纪录
            Boolean saveNewGrade = saveGrade(gradeStrategy, identity, operator);
            if (saveNewGrade) {
                List<Info> gradeInfo = infoBO.getInfo(gradeStrategy.getKey(), identity.getId());
                if (!CollectionUtils.isEmpty(gradeInfo)) {
                    Info historyInfo = gradeInfo.get(0);
                    historyInfo.setDel(-1);
                    infoBO.update(historyInfo, operator);
                }
                Info newInfo = infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), id, operator);
                if (newInfo != null) {
                    result.setSuccess(true);
                } else {
                    logger.error("save Info grade failed ,gradeStrategy :" + JSONObject.toJSONString(gradeStrategy));
                    result.setErrorMsg("保存成绩信息失败!");
                }
            } else {
                logger.error("save grade failed ,gradeStrategy :" + JSONObject.toJSONString(gradeStrategy));
                result.setErrorMsg("保存成绩失败!");
            }
        } else {
            logger.error("get grade failed , gradeStrategy : " + JSONObject.toJSONString(gradeStrategy));
            result.setErrorMsg("获取成绩失败!");
        }
        return result;
    }

    @Override
    public CommonResult<Boolean> checkFinalReplyGrade(Integer id, String operator) {
        if (id == null) {
            return CommonResult.errorReturn("System param error!");
        }
        Identity identity = identityBO.get(id);
        if (identity == null) {
            return CommonResult.errorReturn("该学生信息不存在!");
        }
        CommonResult<Boolean> result = new CommonResult<Boolean>(false, "");
        //指导教师
        List<Info> guideTeacherInfo = infoBO.getInfo(IKEY.GuideName, identity.getId());
        //该学生答辩组教师
        List<Info> guideTeacherID = infoBO.getInfo(IKEY.Guide, identity.getId());
        TeacherGroupVO teacherGroupVO = null;
        if (!CollectionUtils.isEmpty(guideTeacherID)) {
            Integer teacherId = Integer.parseInt(guideTeacherID.get(0).getValue());
            teacherGroupVO = teacherGroupBO.getByTeacher(teacherId);
        }
        //答辩成绩
        List<Grade> replyGrade = getGrade(IKEY.REPLY_GRADE, identity.getId());
        //评阅成绩
        List<Grade> reportGrade = getGrade(IKEY.REPORT_GRADE, identity.getId());
        //指导教师成绩
        List<Grade> guideGrade = getGrade(IKEY.GUIDE_GRADE, identity.getId());
        //查询是否拥有最终答辩成绩
        List<Grade> fReplyGrade = getGrade(IKEY.FINAL_REPLY_GRADE, identity.getId());
        //成绩转换
        Integer guide = null;
        Integer report = null;
        Integer reply = null;
        if (!CollectionUtils.isEmpty(guideGrade)) {
            guide = Integer.parseInt(guideGrade.get(0).getValue());
        }
        if (!CollectionUtils.isEmpty(reportGrade)) {
            report = Integer.parseInt(reportGrade.get(0).getValue());
        }
        if (!CollectionUtils.isEmpty(replyGrade)) {
            reply = Integer.parseInt(replyGrade.get(0).getValue());
        }
        //如果不存在最终答辩成绩 执行生成最终答辩成绩
        if (CollectionUtils.isEmpty(fReplyGrade)) {
            if (!CollectionUtils.isEmpty(guideGrade) && !CollectionUtils.isEmpty(replyGrade) && !CollectionUtils.isEmpty(reportGrade)) {
                //校验成绩规则
                Boolean checkdiff = checkGuideAndReplyGrade(guide, reply);
                if (checkdiff) {
                    Integer finalGrade = getFinalGrade(guide, report, reply);
                    logger.info("学生:" + identity.getName() + ", 最终成绩: " + finalGrade + "guideGrade : " + guide + "report: " + report + " reply :" + reply);
                    Boolean saveFinalGrade = saveGrade(new BasicGradeStrategy(GradeType.Final, IKEY.FINAL_REPLY_GRADE, String.valueOf(finalGrade)), identity, operator);
                    if (saveFinalGrade) {
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.FINAL_REPLY_GRADE, String.valueOf(finalGrade)), identity.getId(), operator);
                        result.setSuccess(true);
                    } else {
                        result.setErrorMsg("保存最终成绩失败!");
                    }
                } else {
                    result.setErrorMsg("(" + identity.getName() + ")  该学生未能生成最终答辩成绩,答辩成绩和指导成绩可上下浮动5分 但是必须在同一分数段。例如: 指导成绩:89 答辩成绩:90 也是不符合规则的。 该学生指导教师: " + guideTeacherInfo.get(0).getValue() + " , 答辩教师小组组长 :" + teacherGroupVO.getParallelism().getIdentityName());
                }
            } else {

            }
        } else {
            //判断查询最终答辩成绩与重新生成答辩成绩是否一致 若不同则更新该学生最终答辩成绩
            Grade fgrade = fReplyGrade.get(0);
            Boolean checkdiff = checkGuideAndReplyGrade(guide, reply);
            if (checkdiff) {
                Integer newFinalGrade = getFinalGrade(guide, report, reply);
                if (StringUtils.isNotBlank(fgrade.getValue())) {
                    Integer fgradeValue = Integer.parseInt(fgrade.getValue());
                    //最新计算的答辩成绩与查询答辩成绩不同  更新最终答辩成绩
                    if (!newFinalGrade.equals(fgradeValue)) {
                        fgrade.setDel(-1);
                        update(fgrade, operator);
                        //逻辑删除 info 表中最终答辩成绩
                        List<Info> oldFinalGradeInfo = infoBO.getInfo(IKEY.FINAL_REPLY_GRADE, identity.getId());
                        Info oldInfo = oldFinalGradeInfo.get(0);
                        oldInfo.setDel(-1);
                        infoBO.update(oldInfo, operator);
                        //重新保存成绩
                        Boolean saveFinalGrade = saveGrade(new BasicGradeStrategy(GradeType.Final, IKEY.FINAL_REPLY_GRADE, String.valueOf(newFinalGrade)), identity, operator);
                        if (saveFinalGrade) {
                            infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.FINAL_REPLY_GRADE, String.valueOf(newFinalGrade)), identity.getId(), operator);
                            result.setSuccess(true);
                        } else {
                            result.setErrorMsg("保存最终成绩失败!");
                        }
                    } else {
                        result.setErrorMsg("成绩一致!");
                    }
                } else {
                    result.setErrorMsg("最终成绩为null");
                }
            } else {
                result.setErrorMsg("(" + identity.getName() + ")  该学生未能生成最终答辩成绩,答辩成绩和指导成绩可上下浮动5分 但是必须在同一分数段。例如: 指导成绩:89 答辩成绩:90 也是不符合规则的。 该学生指导教师: " + guideTeacherInfo.get(0).getValue() + " , 答辩教师小组组长 :" + teacherGroupVO.getParallelism().getIdentityName());
            }
        }
        return result;
    }

    @Override
    public CommonResult<Boolean> checkFinalRepolyGradeAdminRole(Integer id, String operator) {
        if (id == null) {
            return CommonResult.errorReturn("System param error!");
        }
        Identity identity = identityBO.get(id);
        if (identity == null) {
            return CommonResult.errorReturn("该学生信息不存在!");
        }
        CommonResult<Boolean> result = new CommonResult<Boolean>(false, "");
        //答辩成绩
        List<Grade> replyGrade = getGrade(IKEY.REPLY_GRADE, identity.getId());
        //评阅成绩
        List<Grade> reportGrade = getGrade(IKEY.REPORT_GRADE, identity.getId());
        //指导教师成绩
        List<Grade> guideGrade = getGrade(IKEY.GUIDE_GRADE, identity.getId());
        //查询是否拥有最终答辩成绩
        List<Grade> fReplyGrade = getGrade(IKEY.FINAL_REPLY_GRADE, identity.getId());
        //成绩转换
        Integer guide = null;
        Integer report = null;
        Integer reply = null;
        if (!CollectionUtils.isEmpty(guideGrade)) {
            guide = Integer.parseInt(guideGrade.get(0).getValue());
        }
        if (!CollectionUtils.isEmpty(reportGrade)) {
            report = Integer.parseInt(reportGrade.get(0).getValue());
        }
        if (!CollectionUtils.isEmpty(replyGrade)) {
            reply = Integer.parseInt(replyGrade.get(0).getValue());
        }
        //如果不存在最终答辩成绩 执行生成最终答辩成绩
        if (CollectionUtils.isEmpty(fReplyGrade)) {
            if (!CollectionUtils.isEmpty(guideGrade) && !CollectionUtils.isEmpty(replyGrade) && !CollectionUtils.isEmpty(reportGrade)) {
                //校验成绩规则
                Integer finalGrade = getFinalGrade(guide, report, reply);
                logger.info("学生:" + identity.getName() + ", 最终成绩: " + finalGrade + "guideGrade : " + guide + "report: " + report + " reply :" + reply);
                Boolean saveFinalGrade = saveGrade(new BasicGradeStrategy(GradeType.Final, IKEY.FINAL_REPLY_GRADE, String.valueOf(finalGrade)), identity, operator);
                if (saveFinalGrade) {
                    infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.FINAL_REPLY_GRADE, String.valueOf(finalGrade)), identity.getId(), operator);
                    result.setSuccess(true);
                } else {
                    result.setErrorMsg("保存最终成绩失败!");
                }
            } else {

            }
        } else {
            //判断查询最终答辩成绩与重新生成答辩成绩是否一致 若不同则更新该学生最终答辩成绩
            Grade fgrade = fReplyGrade.get(0);
            Integer newFinalGrade = getFinalGrade(guide, report, reply);
            if (StringUtils.isNotBlank(fgrade.getValue())) {
                Integer oldFinalGrade = Integer.parseInt(fgrade.getValue());
                if (!newFinalGrade.equals(oldFinalGrade)) {
                    fgrade.setDel(-1);
                    update(fgrade, operator);
                    //逻辑删除 info 表中最终答辩成绩
                    List<Info> oldFinalGradeInfo = infoBO.getInfo(IKEY.FINAL_REPLY_GRADE, identity.getId());
                    Info oldInfo = oldFinalGradeInfo.get(0);
                    oldInfo.setDel(-1);
                    infoBO.update(oldInfo, operator);
                    //重新保存成绩
                    Boolean saveFinalGrade = saveGrade(new BasicGradeStrategy(GradeType.Final, IKEY.FINAL_REPLY_GRADE, String.valueOf(newFinalGrade)), identity, operator);
                    if (saveFinalGrade) {
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.FINAL_REPLY_GRADE, String.valueOf(newFinalGrade)), identity.getId(), operator);
                        result.setSuccess(true);
                    } else {
                        result.setErrorMsg("保存最终成绩失败!");
                    }
                } else {
                    result.setErrorMsg("成绩一致!");
                }
            } else {
                result.setErrorMsg("最终成绩为null");
            }
        }
        return result;
    }

    public List<Grade> getGrade(String key, Integer id) {
        List<Grade> result = Lists.newArrayList();
        if (StringUtils.isEmpty(key) || id == null) {
            return result;
        }
        Example example = new Example();
        example.createCriteria().andEqualTo("`key`", key).andEqualTo("del", "0").andEqualTo("identity_id", id);
        result = gradesDAO.selectByExample(example);
        return result;
    }

    @Override
    public CommonResult<Boolean> clearReplyGrade(Integer id, String key, String operator) {
        if (id == null || StringUtils.isEmpty(key)) {
            return CommonResult.errorReturn("System param error!");
        }
        Identity identity = identityBO.get(id);
        if (identity == null) {
            return CommonResult.errorReturn("该学生信息不存在!");
        }
        CommonResult<Boolean> result = new CommonResult<Boolean>(true, "");

        List<Grade> cleaGrade = getGrade(key, id);
        List<Info>  clearInfo = infoBO.getInfo(key, id);

        List<Grade> finalGrade = getGrade(IKEY.FINAL_REPLY_GRADE, id);
        List<Info>  finalGradeInfo = infoBO.getInfo(IKEY.FINAL_REPLY_GRADE, id);

        if (!CollectionUtils.isEmpty(cleaGrade)){
            Grade oldGrade = cleaGrade.get(0);
            oldGrade.setDel(-1);
            update(oldGrade, operator);
        }

        if (!CollectionUtils.isEmpty(clearInfo)){
            Info oldInfo = clearInfo.get(0);
            oldInfo.setDel(-1);
            infoBO.update(oldInfo, operator);
        }

        if (!CollectionUtils.isEmpty(finalGrade)){
            Grade oldFinaleGrade = finalGrade.get(0);
            oldFinaleGrade.setDel(-1);
            update(oldFinaleGrade, operator);
        }

        if (!CollectionUtils.isEmpty(finalGradeInfo)){
            Info oldFinalGradeInfo = finalGradeInfo.get(0);
            oldFinalGradeInfo.setDel(-1);
            infoBO.update(oldFinalGradeInfo, operator);
        }

        if (key.equals(IKEY.REPLY_GRADE)){
            List<Grade> reportGrade = getGrade(IKEY.REPORT_GRADE, id);
            List<Info> reportGradeInfo = infoBO.getInfo(IKEY.REPORT_GRADE, id);

            if (!CollectionUtils.isEmpty(reportGrade)){
                Grade oldReportGrade = reportGrade.get(0);
                oldReportGrade.setDel(-1);
                update(oldReportGrade, operator);
            }
            if (!CollectionUtils.isEmpty(reportGradeInfo)){
                Info oldReportInfo = reportGradeInfo.get(0);
                oldReportInfo.setDel(-1);
                infoBO.update(oldReportInfo, operator);
            }

        }
        return result;
    }

    /**
     * <p>功能描述：根据ID校验是否终止答辩</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-03-06 02:33:47</p>
     *
     * @param id
     * @return 返回值为 true 标识终止答辩 false为未终止
     */
    private Boolean checkingStopById(Integer id) {
        Boolean result = false;
        if (id == null) {
            return result;
        }
        //根据key查询出所有该key记录
        List<Info> infoList = infoBO.getInfo(IKEY.GRADE_STOP_KEY, id);
        if (!infoList.isEmpty()) {
            result = true;
        }
        return result;
    }

    /**
     * <p>功能描述：校验开题成绩是否通过</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-04-24 09:56:26</p>
     *
     * @param id
     * @return
     */
    private Boolean checkOpenGrade(Integer id) {
        Boolean result = false;
        if (id == null) {
            return result;
        }
        List<Grade> gradeList = getGrade(IKEY.OPEN_GRADE, id);
        if (CollectionUtils.isNotEmpty(gradeList)) {
            Grade grade = gradeList.get(0);
            if (grade.getValue().equals("YES")) {
                result = true;
            }
        }
        return result;
    }

    /**
     * <p>功能描述: 验证中期成绩是否通过</p>
     * <p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-16 15:04:19</p>
     *
     * @param id
     * @return
     */
    private Boolean checkInterimGrade(Integer id) {
        Boolean result = false;
        if (id == null) {
            return result;
        }
        List<Grade> systemGrade = getGrade(IKEY.INTERIM_GRADE, id);
        if (CollectionUtils.isNotEmpty(systemGrade)) {
            Grade grade = systemGrade.get(0);
            if (StringUtils.isNotBlank(grade.getValue())) {
                Integer gradeValue = Integer.parseInt(grade.getValue());
                if (gradeValue != null && gradeValue > 0) {
                    result = true;
                }
            } else {
                logger.error("grade  key : interimGade  value is null");
            }
        } else {
            logger.error(" get interim grade  is null , id : " + id);
        }
        return result;
    }

    /**
     * <p>功能描述：插入成绩后 插入info表及状态</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-16 20:27:57</p>
     *
     * @param gradeStrategy
     * @param times
     * @param id
     * @param operator
     * @return
     */
    private Boolean saveInfoByTimes(GradeStrategy gradeStrategy, GradeTimeType times, Integer id, String operator) {
        Boolean result = true;
        if (gradeStrategy == null || times == null || id == null) {
            result = false;
            return result;
        }
        if (times.equals(GradeTimeType.GRADE_STOP)) {
            infoBO.save(new BasicInfoStrategy(InfoType.GRADE, IKEY.GRADE_STOP_KEY, IKEY.SYSTEM_GRADE), id, operator);
        } else {
            infoBO.save(new BasicInfoStrategy(InfoType.GRADE, gradeStrategy.getKey(), gradeStrategy.getValue()), id, operator);
            switch (times) {
                //一辩二辩成绩标志  value值 为当次成绩
                case SYSTEM_GRADE_ONE:
                    //一辩通过 打上一辩标志
                    if (gradeStrategy.getValue().equals("YES")) {
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, GradeTimeType.REPLY_GRADE_ONE.getKey(), IKEY.SYSTEM_GRADE), id, operator);
                    } else {
                        //未通过 打上二辩标志
                        infoBO.save(new BasicInfoStrategy(InfoType.GRADE, GradeTimeType.SYSTEM_GRADE_TWO.getKey(), IKEY.SYSTEM_GRADE), id, operator);
                    }
                    break;
                case SYSTEM_GRADE_TWO:
                    //二次系统验收   只有  通过 和 终止答辩
                    infoBO.save(new BasicInfoStrategy(InfoType.GRADE, GradeTimeType.REPLY_GRADE_TWO.getKey(), IKEY.SYSTEM_GRADE), id, operator);
                    break;
            }
        }
        return result;
    }

    /**
     * <p>功能描述: 转换存储</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-16 20:42:25</p>
     *
     * @param gradeStrategy
     * @param identity
     * @param operator
     * @return
     */
    private Boolean saveGrade(GradeStrategy gradeStrategy, Identity identity, String operator) {
        Boolean result = true;
        Grade grade = new Grade();
        grade.setType(String.valueOf(gradeStrategy.getType()));
        grade.setKey(gradeStrategy.getKey());
        grade.setValue(gradeStrategy.getValue());
        grade.setIdentityId(identity.getId());
        grade.setIdentityName(identity.getName());
        grade.setIdentityRole(identity.getRole());
        grade.setDel(0);
        CommonResult<Grade> saveResult = save(grade, operator);
        if (!saveResult.isSuccess()) {
            result = false;
        }
        return result;
    }

    /**
     * <p>功能描述：校验系统验收成绩是否存在</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-27 23:01:20</p>
     *
     * @param id
     * @return
     */
    public Boolean checkSystemGrade(Integer id) {
        Boolean result = false;
        if (id == null) {
            return result;
        }
        List<Grade> gradeList = getGrade(IKEY.SYSTEM_GRADE, id);
        if (!CollectionUtils.isEmpty(gradeList)) {
            result = true;
        }
        return result;
    }

    /**
     * <p>功能描述：答辩成绩和指导成绩比较</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-28 09:03:39</p>
     *
     * @param guide
     * @param reply
     * @return
     */
    private Boolean checkGuideAndReplyGrade(Integer guide, Integer reply) {
        Boolean result = false;
        int guidOne = guide / 10;
        int replyOne = reply / 10;
        if (guidOne == replyOne) {
            int diff = guide - reply;
            if (Math.abs(diff) <= 5) {
                result = true;
            }
        }
        return result;
    }

    /**
     * <p>功能描述：计算答辩成绩</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-28 09:55:47</p>
     *
     * @param guide
     * @param report
     * @param reply
     * @return
     */
    private Integer getFinalGrade(Integer guide, Integer report, Integer reply) {
        double result = (guide * 0.4) + (report * 0.2) + (reply * 0.4);
        BigDecimal checkNumber = new BigDecimal(result).setScale(0, BigDecimal.ROUND_HALF_UP);
        return checkNumber.intValue();
    }

}
